package com.taysear.parcel;

import java.util.Date;
import javax.persistence.EntityManager;

import com.taysear.parcel.domain.Bus;
import com.taysear.parcel.domain.Employee;
import com.taysear.parcel.domain.Loadingsheet;
import com.taysear.parcel.domain.LoadingsheetAction;
import com.taysear.parcel.domain.LoadingsheetHistory;
import com.taysear.parcel.domain.LoadingsheetStatus;
import com.taysear.parcel.domain.Route;
import com.taysear.parcel.domain.RouteTime;
import com.taysear.parcel.domain.Substation;
import com.taysear.parcel.fieldfactory.LoadingsheetFieldFactory;
import com.taysear.parcel.util.Constants;
import com.vaadin.data.util.BeanItem;
import com.vaadin.ui.Button;
import com.vaadin.ui.Form;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.themes.Reindeer;

public class LoadingsheetForm extends Form{
	ParcelApplication app;
	Loadingsheet bean;
	Button save;
	Button createAnother;
	LoadingsheetWindow loadingsheetWindow;
	LoadingsheetFieldFactory fieldFactory;
	
	public LoadingsheetForm(final ParcelApplication app, final LoadingsheetWindow loadingsheetWindow, String caption, Boolean isEdit) {
		super();
		this.app = app;
		this.loadingsheetWindow = loadingsheetWindow;

		setCaption(caption);
		setWriteThrough(false); // we want explicit 'apply'
		setInvalidCommitted(false); // no invalid values in datamodel

		// FieldFactory for customizing the fields and adding validators
		fieldFactory = new LoadingsheetFieldFactory(app);
		setFormFieldFactory(fieldFactory);
		
		save = new Button("Save");
		save.addStyleName("blueButton");
		save.setDisableOnClick(true);
		save.addListener(new Button.ClickListener() {
				public void buttonClick(ClickEvent event) {
					try {
						if(isValid()){
							commit();
						}else {
				               	app.showNotification("Invalid Input: Please ensure all required fields contain valid data before saving.");
				               	save.setEnabled(true);
				               }
					} catch (Exception e) {
						// Ignored, we'll let the Form handle the errors
					}
				}
			});
	
		createAnother = new Button("Create Another");
		createAnother.addStyleName("greenButton");
		createAnother.addListener(new Button.ClickListener() {
				public void buttonClick(ClickEvent event) {
					setReadOnly(false);
					discard();
					save.setEnabled(true);
					createAnother.setEnabled(false);
				}
			});
		createAnother.setEnabled(false);
		if(isEdit){
			createAnother.setVisible(false);
		}
		
		Button close = new Button("Close");
		close.addStyleName("grayButton");
		close.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                Window editWindow = (Window) event.getButton().getParent().getParent().getParent().getParent().getParent();
            	(editWindow.getParent()).removeWindow(editWindow);
            }
        });
		
		HorizontalLayout buttons = new HorizontalLayout();
		buttons.setSpacing(true);
		buttons.addComponent(save);
		buttons.addComponent(createAnother);
		buttons.addComponent(close);
		getFooter().addComponent(buttons);
		getFooter().setMargin(false, false, true, true);
	}
	
	public void initForm(){
		bean = new Loadingsheet(); 
		bean.setOrigin(app.getUser().getEmployee().getSubstation());
		BeanItem<Loadingsheet> beanItem = new BeanItem<Loadingsheet>(bean);
		setItemDataSource(beanItem);
	}
	
	@Override
	public void commit() {
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			if(bean.getLoadingsheetId() == null){
				save(em);
				em.getTransaction().commit();
				loadingsheetWindow.date.setValue(new Date());
				setReadOnly(true);
				createAnother.setEnabled(true);
				save.setEnabled(false);
			}
			else{ 
				edit(em);
				em.getTransaction().commit();
			}
			loadingsheetWindow.searchLoadingsheet();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			//super.commit();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
		}
	}
	
	public void save(EntityManager em){
		RouteTime routeTime = em.find(RouteTime.class, getField("routeTime").getValue());
		Substation origin = em.find(Substation.class, getField("origin").getValue());
		Substation destination = em.find(Substation.class, getField("destination").getValue());
		LoadingsheetStatus loadingsheetStatus = em.find(LoadingsheetStatus.class, Constants.LOADINGSHEET_STATUS_NEW); // new
		
		Loadingsheet loadingsheet = new Loadingsheet();
		fillLoadingsheet(em, loadingsheet);
		loadingsheet.setRouteTime(routeTime);
		loadingsheet.setOrigin(origin);
		loadingsheet.setDestination(destination);
		loadingsheet.setDate(new Date());
		loadingsheet.setLoadingsheetStatus(loadingsheetStatus);
		em.persist(loadingsheet);
		
		LoadingsheetAction loadingsheetAction = em.find(LoadingsheetAction.class, Constants.LOADINGSHEET_ACTION_CREAT);
		saveLoadingsheetHistory(em, loadingsheet, loadingsheetAction, "created");
	}
	
	public void edit(EntityManager em) throws Exception{
		Loadingsheet loadingsheet = em.find(Loadingsheet.class, bean.getLoadingsheetId());
		em.refresh(loadingsheet);
		LoadingsheetStatus loadingsheetStatus = em.find(LoadingsheetStatus.class, Constants.LOADINGSHEET_STATUS_EDITED); // edited
		if(loadingsheet.getLoadingsheetStatus().getLoadingsheetStatusId() == Constants.LOADINGSHEET_STATUS_CANCELLED){ // cancelled
			app.showNotification("Loadingsheet is cacelled, edit is not possible.");
			save.setEnabled(false);
			throw new Exception("Loadingsheet is cancelled, edit not possible");
		} else{
			fillLoadingsheet(em, loadingsheet);
			loadingsheet.setLoadingsheetStatus(loadingsheetStatus);
			em.merge(loadingsheet);
			
			LoadingsheetAction loadingsheetAction = em.find(LoadingsheetAction.class, Constants.LOADINGSHEET_ACTION_EDIT);
			saveLoadingsheetHistory(em, loadingsheet, loadingsheetAction, "edited");
		}
	}
	
	public Loadingsheet fillLoadingsheet(EntityManager em, Loadingsheet loadingsheet){
		Bus bus = em.find(Bus.class, getField("bus").getValue());
		Employee driver = em.find(Employee.class, getField("driver").getValue());
		Employee conductor = em.find(Employee.class, getField("conductor").getValue());
		
		loadingsheet.setBus(bus);
		loadingsheet.setDriver(driver);
		loadingsheet.setConductor(conductor);
		return loadingsheet;
	}
	
	private void saveLoadingsheetHistory(EntityManager em, Loadingsheet loadingsheet, LoadingsheetAction loadingsheetAction, String desc){
		LoadingsheetHistory loadingsheetHistory = new LoadingsheetHistory();
		loadingsheetHistory.setLoadingsheet(loadingsheet);
		loadingsheetHistory.setDate(new Date());
		loadingsheetHistory.setDescription("Loadingsheet is " + desc);
		loadingsheetHistory.setLoadingsheetAction(loadingsheetAction);
		loadingsheetHistory.setUser(app.getUser());
		em.persist(loadingsheetHistory);
	}
}
